06. If 语句

If 语句

很多编译器会尝试优化 if 语句。如果你这么写:

int x = 7;

if (x > 0) {
  return y;
}
if (x <= 0) {
   return z;
}

优化后可能是:

int x = 7;
if (x > 0) {
   return y;
}
else {
   return z;
}

编译器不会真正把你的 C++ 代码重写为优化后的代码。它在输出汇编语言或机器语言时或进行优化。但总体来说,如果 if 的逻辑分支对 CPU 资源占用较多,需要避免过多的逻辑分支。

考虑到 if 语句的执行过程,建议把大多数的用例放到更高层次的逻辑分支上,这样更高效。

下面是一个简单的例子:

    for (int i = 0; i < 1000; i++) {
        if (i > 0 && i < 5) {
            cout <<  "low \n";
        }
        else if (i >= 990) {
            cout << "high \n";
        }
        else {
            cout << "normal \n";
        }
    }

在大多数情况下,上述代码都会输出单词 “normal”。在大多数时间里,这段代码需要遍历所有的 if 和 else 分支,因此,CPU 会比较每个分支中的 i

如果把 “normal” 放到分支顶部,而不是底部,效率会更高。

for (int i = 0; i < 1000; i++) {
    if (i >= 5 && i < 990) {
        cout <<  "normal \n";
    }
    else if (i >= 990) {
        cout << "high \n";
    }
    else {
        cout << "low \n";
    }
}

这样修改后,CPU 在大多数时间里就能跳过 else if 和 else 分支了。

If 语句在 CPU 上的执行

使用 C++ 等高级语言时,if 语句还有一方面不太好控制。CPU 会运行同步运算,试图优化 if 语句的运算。

进行运算时,CPU 会提前执行后面的代码,并行开启另一个运算。对 if 语句而言,CPU 会尝试预测接下来进行哪个分支,然后在预测的分支内运行运算。需要评估逻辑表达时,CPU 可能会意识到,预测不够准确。如果预测错误,则预测的运算会停止,CPU 开始运行正确的运算。

因此,重排或删除 if 语句可能不会显著缩短时间。因为编译器和 CPU 已经在尝试优化相关操作了。

练习

在下面部分,我们来做一个 if 语句的优化练习。